perm filename ODSK.FAI[CMS,LCS] blob
sn#377223 filedate 1978-08-29 generic text, type T, neo UTF8
00100 ;Floppy disk file system.
00200 .INSERT ASMBL.FAI[CMS,LCS]
00300 RETRY ← =10 ;Number of retrys until error.
00400 DMARK ← 74 ;Directory mark
00500 FMARK ← 72 ;File mark
00600 HMARK ← 67 ;Hole mark?
00700 LASTRK ← =34 ;Last track
00800 ZERO ← 274 ↔ LOC ZERO ;Fail offset
00900 CBLK: 0 ;Ram command block.
01000 CCNT: 0 ;C parameter count.
01100 CLEN: 0 ;C # of sectors.
01200 CSEC: 0 ;C sector
01300 CTRK: 0 ;C track
01400 0
01500 FOTRK: 0 ;Format track number.
01600 0
01700 FCMD: 0 ;Disk command pointer.
01800 FCMDH: 0
01900 CMDJMP: 0 ;Indirect command jump.
02000 CJMPH: 0 ;Msbyte.
02100 ERFLG: 0 ;Error flag/code.
02200 SVERR: 0 ;Saved error.
02300 CEFLG: 0 ;Communication error flag.
02400 RFOPEN: 0 ;Read file open flag.
02500 WFOPEN: 0 ;Write file open flag
02600 DIRC: 0 ;Data direction
02700 FLEN: 0 ;File length. In sectors.
02800 SREM: 0 ;Sectors remaining.
02900 NTRYS: 0 ;Number of retrys before error.
03000 BUSY: 0 ;Busy flag
03100 MO: 0 ;Motor on flag. MFLG = TL or TH?
03200 TL: 0 ;Motor time out low.
03300 TH: 0 ;Time out high.
03400 DIRCNT: 0 ;Directory sector count
03500 HTRK: 0 ;Hole track number
03600 HSEC: 0 ;Hole sector number
03700 SVHY: 0 ;Hole directory index.
03800 SVHSEC: 0 ;Hole directory sector.
03900 FBLK: 0 ;File block
04000 FNAME: BLOCK 11 ;9 Chr file name.
04100 NSEC: 0 ;Number of sectors in file.
04200 FTRK: 0 ;Disk track number
04300 FSEC: 0 ;Disk sector number
04400 BLOCK 3
04500 DBLK: 0 ;Directory block
04600 DSEC: 0 ;Number of sectors in directory.
04700 FFDIR: 0 ;First free directory block
04800 FFTRK: 0 ;First free data track
04900 FFSEC: 0 ;First free data sector
05000 FBLKS: 0 ;Number of free sectors. In sectors.
05100 FBH: 0 ;Msbyte
05200 0
05300 CKSUM: 0 ;Check sum.
05400 SPOINT: 0 ;SI/O pointer.
05500 SPOH: 0 ;Msbyte
05600 DPOINT: 0 ;Disk buffer bointer.
05700 DPOH: 0 ;Msbyte
05800 LOC ZERO+1000
05900 FBUF: 0 ;Disk buffer
06000 LOC FBUF + 400
06100 FBUF1: 0 ;Other disk buffer.
00100 FCTBL: LOC ZERO+174000 ;PROM Start address.
00200 DINIT ← 0
00300 65 ;Specify
00400 4 ;Parameter count.
00500 252 ;H unload I cnt./ H load time.
00600 =25 ;Head settling time in ms*2.
00700 =20 ;Step rate in ms*2.
00800 15 ;Init
00900 SBT ← 6
01000 65 ;Specify
01100 4
01200 0 ;Current track.
01300 377
01400 377 ;No bad tracks.
01500 20 ;Surface zero bad tracks command.
01600 DMA ← 14
01700 172 ;Write special register.
01800 2
01900 0 ;DMA and double actuator.
02000 27 ;Mode register.
02100 RESTOR ← 20
02200 151 ;Seek track zero command.
02300 1 ;With head load.
02400 0 ;Track zero
02500 MON ← 23
02600 172 ;Write special register.
02700 2 ;Clear out pins.
02800 40 ;Optional output / motor on bit.
02900 43 ;Drive control output register.
03000 MOFF ← 27
03100 172 ;Write special register.
03200 2 ;Clear out pins.
03300 0 ;Optional output / motor off.
03400 43 ;Drive control output register.
03500 RHDR0 ← 33
03600 RH0: 123 ;Read two sectors command.
03700 3
03800 2 ;# of sectors.
03900 1 ;Header sector number
04000 0 ;Header track number
04100 WHDR0 ← 40
04200 WH0: 113 ;Write two sectors command.
04300 3
04400 2 ;# of sectors.
04500 1 ;Header sector number.
04600 0 ;Header track number.
04700 RDSTAT ← 45
04800 154 ;Read drive status command.
04900 0
05000 ID0: 113 ;Write two sectors.
05100 3
05200 =16 ;# of sectors.
05300 1 ;First sector.
05400 0 ;Track zero.
05500 FORMT: 143 ;Format track command.
05600 5
05700 =16 ;Gap 1 -6.
05800 0 ;Gap 5. No index mark.
05900 =16 ;Sectors per track.
06000 =27 ;Gap 3 -6.
06100 0 ;Format track number.
00100 ;Restore bug in 8271?
00200 ;Put GEOT in DECODE.
00300 ;Add restore to retry?
00400 ;COMERRs ? In ACK?
00500 ;Add write protect and not ready error codes.
00600 ;Flush other dir. = LASTRK?
00700
00800 ;Power on reset.
00900 RST: LDXI 377 ;Setup stack.
01000 TXS
01100 CLD ;Clear decimal mode.
01200
01300 ;Reset I/O
01400 SIOC ← 20000 ;SI/O command register.
01500 SIOD ← 20001 ;SI/O data register.
01600 FDSKC ← 10000 ;Disk command/status register
01700 FDSKP ← 10001 ;Disk parameter/result register
01800 FDSKR ← 10002 ;Disk reset register.
01900 FDRQ ← 14000 ;Disk DMA data request
02000
02100 ;Init floppy disk controller.
02200 LDAI 1 ;Reset disk again.
02300 STA FDSKR
02400 NOP
02500 NOP
02600 NOP
02700 LSRA ;Clear A
02800 STA FDSKR
02900
03000 LDAI DINIT ;Disk initialization command.
03100 JSR PCMD ;Prom command.
03200 LDAI DMA ;Setup DMA mode.
03300 JSR PCMD
03400 LDXI 377
03500 STXZ TL
03600 LDAI 10
03700 STAZ TH
03800 RLOOP: DEX
03900 BNE RLOOP
04000 DECZ TL
04100 BNE RLOOP
04200 DECZ TH
04300 BNE RLOOP
04400
04500 LDAI RESTOR ;Restore track zero.
04600 JSR PCMD ;Add delay? Read sp. reg?
04700
04800 LDAI SBT ;Setup bad tracks
04900 JSR PCMD
05000 LDA FDSKP ;Read result reg. to clr int.?
05100 ;Reset SI/O
05200 LDAI 3 ;Reset bits
05300 STA SIOC
05400 LDAI 25 ;ACIA control word.
05500 STA SIOC
05600
05700 ;Init RAM
05800 LDAZ DSEC
05900 STAZ DIRCNT ;Point to end of directory.
06000 LDAI 0
06100 STAZ MO ;Init motor flag.
00100 IDLSET: LDAI 0
00200 STAZ RFOPEN ;Reset read file open flag.
00300 STAZ WFOPEN ;Clear write file open flag.
00400
00500 STAZ CEFLG ;Clear comm. error flag.
00600 STAZ ERFLG ;Clear error flag.
00700 STAZ SVERR ;Clear other error flag.
00800
00900 STAZ DIRC ;Set disk to read.
01000 STAZ BUSY ;Set to not busy.
01100 TAX ;Start lsbyte of motor time out.
01200 CLI ;Enable interrupts?
01300
01400 TWOS ← 3 ;3 = 1.77s, 4 = 2.3s.
01500 ; JSR IDLEW ?
01600 IDLE: BITZ MO ;Check if motor on.
01700 BPL GSOH
01800 LDA SIOC ;Read SI/O status.
01900 LSRA ;Get rcvr. full bit.
02000 BCS GSOH
02100
02200 DEX ;Time out countdown.
02300 BNE IDLE
02400 DECZ TL
02500 BNE IDLE
02600 DECZ TH
02700 BNE IDLE
02800 JSR MOTOFF ;Turn off motor.
02900 ;Check for file open??
03000 ; JMP IDLSET ?
03100
03200 GSOH: JSR GCHR ;Wait for SOH.
03300 CMPI 1 ;<SOH>.
03400 BNE ILLCMD ;Error.
03500 JSR GCHR ;Wait for command.
00100 DCODE: LDXI NCMDS ;# of commands.
00200 DL: CMPX CMDTBL ;Check if valid command.
00300 BEQ JCMD
00400 DEX
00500 BPL DL
00600 ;Illegal command.
00700 ILLCMD: LDXI 4 ;Command error code.
00800 OCLR: JSR OCHR ;Output status.
00900 JMP IDLSET ;Reset flags.
01000
01100 JCMD: LDAX JLTBL ;Get lsbyte of jump address.
01200 STAZ CMDJMP
01300 LDAX JHTBL ;Get msbyte.
01400 STAZ CJMPH
01500
01600 JMPIN CMDJMP ;Excute command.
01700 ;Fix JMPIN in ASMBL.FAI.
01800
01900 NCMDS ← =9 ;# of commands -1.
02000 ;Swap order for faster DECODE?
02100 CMDTBL: "W" ;Write data
02200 "R" ;Read data
02300 "E" ;Enter write file.
02400 "C" ;Close write file.
02500 "O" ;Open read file.
02600 "K" ;Delete file.
02700 "D" ;Open directory.
02800 "N" ;Next directory block.
02900 "B" ;Free blocks
03000 "P" ;Perform special function.
03100
03200 ;Check all funny addresses.
03300 JLTBL: WRITE∧377 ;Lsbyte of command address.
03400 READ∧377
03500 ENTR∧377
03600 CLOZE∧377
03700 OPIN∧377
03800 KIL∧377
03900 DIR∧377
04000 NXTDIR∧377
04100 BLKS∧377
04200 PSF∧377
04300
04400 JHTBL: WRITE⊗-10 ;Msbyte of command address.
04500 READ⊗-10
04600 ENTR⊗-10
04700 CLOZE⊗-10
04800 OPIN⊗-10
04900 KIL⊗-10
05000 DIR⊗-10
05100 NXTDIR⊗-10
05200 BLKS⊗-10
05300 PSF⊗-10
00100 ;Write command to FDSKC. No wait or * NTRYS.
00200 PCMD: STAZ FCMD ;Prom command with no retrys.
00300 LDAI 370 ;Msbyte of command table addr.
00400 STAZ FCMDH
00500 LDAI 0
00600 STAZ NTRYS
00700 BEQ WCMD ;Jump.
00800
00900 RCMD: LDAI 0 ;Ram command with no retrys.
01000 STAZ NTRYS
01100 TRY: LDAI 0
01200 STAZ FCMD
01300 STAZ FCMDH
01400
01500 WCMD: LDAI 377 ;Set busy.
01600 STAZ BUSY ;?
01700 LDAI 0
01800 STAZ DPOINT ;Reset disk DMA pointer.
01900
02000 BSYW: LDA FDSKC ;Wait until not busy.
02100 BMI BSYW
02200 ; ANDI 100 Command full bit.
02300 ; BNE BSYW Wait until cmd. reg. empty.
02400
02500 LDYI 0
02600 LDAIY FCMD ;Get command code.
02700 STA FDSKC ;Write in disk control reg.
02800
02900 INCZ FCMD ;Point to parameter count.
03000 LDAIY FCMD ;Get count.
03100 BEQ NOPAR ;If no parameters
03200 TAY
03300
03400 ;FULLW: LDA FDSKC Read disk status.
03500 ; ANDI 100 Command full bit.
03600 ; BNE FULLW Wait until empty?
03700
03800 PARW: LDA FDSKC ;Read status
03900 ANDI 40 ;P reg full bit.
04000 BNE PARW ;Wait if still full.
04100
04200 LDAIY FCMD ;Parameter
04300 STA FDSKP
04400 DEY
04500 BNE PARW ;More left?
04600
04700 NOPAR: RTS
04800
04900 ;Disk command with retrys on read error.
05000 RCMDR: LDAI RETRY
05100 STAZ NTRYS
05200 JSR TRY ;RAM disk command.
05300 RTS
05400
05500 RCMDW: JSR RCMDR ;Read command wait.
05600 BW: BITZ BUSY
05700 BMI BW ;Wait until done
05800 LDAZ ERFLG ;Get error bits.
05900 RTS ;Return with error bits.
00100 ;IRQ maskable interrupt routines.
00200 IRQV: PHA ;Save Registers.
00300 TYA
00400 PHA
00500
00600 ;Wait for result bit?
00700 LDA FDSKP ;Read disk result register.
00800 ANDI 36 ;Flush ddbit
00900 STAZ ERFLG
01000 BNE DSKERR ;Disk error.
01100 BITZ DIRC ;Check if write.
01200 BPL NOTBSY ;No errors.
01300 LDAI 0
01400 STAZ DIRC ;Not write.
01500 LDAZ CBLK
01600 CMPI 143 ;Check if format command.
01700 BEQ NOTBSY
01800
01900 LDAI 137 ;Disk verify command.
02000 STAZ CBLK
02100 JSR WCMD ;Verify write.
02200
02300 JMP RTRN ;Wait until done.
02400
02500 DSKERR: ANDI 20 ;Bad bit
02600 BEQ CKTRY
02700 ;Dsk error: RDY,WRT fault, etc.
02800 STAZ SVERR ;Save bad error.
02900 LDAI RDSTAT ;Read dirve status.
03000 JSR PCMD ;No interrupt.
03100 LDA FDSKP ;Read result register.
03200 ;Put error routine someplace else?
03300 ;20 Not ready.
03400 ;21 Write protect.
03500 ;22 Restore error.
03600 ;23 File not found.
03700 ;30 Sector not found.
03800 ;Read drive status if not ready for clear.
03900 JMP NOTBSY
04000
04100 CKTRY: LDAZ NTRYS
04200 BEQ SETERR
04300
04400 DECZ NTRYS
04500 JSR WCMD ;Retry command.
04600 JMP RTRN ;Wait until done.
04700
04800 SETERR: LDAI 377 ;Retry error.
04900 STAZ SVERR
05000
05100 NOTBSY: LDAI 0
05200 STAZ BUSY ;Set done
05300 STAZ DIRC ;Reset to read.
05400
05500 RTRN: PLA ;Restore Registers.
05600 TAY
05700 PLA
05800 RTI ;Return
00100 ;Non-maskable DRQ interrupt.
00200 NMIV: PHA ;Save registers
00300 TYA
00400 PHA
00500 LDYI 0 ;No index.
00600
00700 BITZ DIRC ;Get direction.
00800 BMI WDRQ ;Disk write.
00900
01000 LDA FDRQ ;Read byte from disk.
01100
01200 STAIY DPOINT ;Save it in FBUF
01300 JMP INCPO ;Increment disk buffer pointer.
01400
01500 WDRQ: LDAIY DPOINT ;Get byte from FBUF.
01600 STA FDRQ ;Write in disk data register.
01700
01800 INCPO: INCZ DPOINT
01900
02000 PLA ;Restore registers.
02100 TAY
02200 PLA
02300 RTI ;Return
00100 ;Directory look up.
00200 ;Returns with file found, fnf, or read error.(0,200,XX)
00300 LOKUP: LDXI 0
00400 GNAME: JSR GCHR ;Get name.
00500 STAZX FNAME
00600 INX
00700 CPXI =10 ;9 Chr file name + EOT.
00800 BCC GNAME
00900
01000 CMPI 4 ;EOT
01100 BEQ GHD
01200 PLA ;One level pop to ILLCMD.
01300 PLA
01400 JMP ILLCMD
01500
01600 GHD: JSR RHDR ;Read directory header sector.
01700 BNE LUERR
01800 LDAI FMARK
01900 STAZ FBLK
02000
02100 GETS: JSR RNDS ;Read next 2 directory sectors.
02200 BNE LUERR
02300 LDYI 0
02400 CKDIR: LDXI 0
02500 CKNAM: LDAY FBUF
02600 CMPZX FBLK ;Look for file name.
02700 BNE NXTF ;No match
02800 INY
02900 INX
03000 CPXI =11 ;9 chrs. + fmark + 1.
03100 BCC CKNAM
03200 ;Names match
03300 FMOV: LDAY FBUF ;Save file record.
03400 STAZX FBLK
03500 INY
03600 INX
03700 CPXI 20
03800 BCC FMOV
03900
04000 LDAI 0 ;Return with file found.
04100 LUERR: RTS ;Return with error bits.
04200
04300 NXTF: TYA ;Point to next file record.
04400 ORAI 17
04500 TAY
04600 INY
04700 BNE CKDIR
04800
04900 DECZ SREM ;Check if more sectors.
05000 DECZ SREM
05100 BNE GETS
05200 LDAI 200 ;Return file not found code.
05300 RTS
00100 ;Read 1st sec of a directory. Returns with 0 or Ebits.
00200 RHDR: JSR MOTON ;Turn on motor and delay.
00300 LDXI 4
00400 CSET: LDAX RH0 ;Setup command list.
00500 STAZX CBLK
00600 DEX
00700 BPL CSET
00800
00900 JSR SETDPO ;Point disk to FBUF.
01000 JSR RSEC ;Read it * 16.
01100 BNE HERR
01200 LDA FBUF
01300 CMPI DMARK ;Check for directory.
01400 BNE HERR
01500
01600 GHDR: LDXI 7
01700 GHL: LDAX FBUF
01800 STAZX DBLK
01900 DEX
02000 BPL GHL
02100 LDAZ DSEC
02200 STAZ SREM ;Number of sectors in dir.
02300 STAZ DIRCNT ;Reset directory count.
02400 LDAI 0 ;No error return
02500 HERR: RTS ;Return with error bits.
02600
02700 ;Read next dir. sector. Returns with error bits.
02800 RNDS: INCZ CSEC ;Read next dir sec.
02900 INCZ CSEC
03000 RSEC: JSR RCMDW ;Disk command wait * RETRYS
03100 BEQ GOTIT ;Good read
03200 LDAI LASTRK ;Last track
03300 STAZ CTRK
03400 JSR RCMDW
03500 LDAI 0 ;Fix CTRK for next read.
03600 STAZ CTRK
03700 LDAZ ERFLG ;Get error bits.
03800 GOTIT: RTS ;Return with error bits.
03900
04000 SETDPO: LDAI 0 ;Point disk to FBUF
04100 STAZ DPOINT
04200 LDAI FBUF⊗-10
04300 STAZ DPOH
04400 RTS
00100 ;Open read file.
00200 OPIN: BITZ WFOPEN ;Check if write file open.
00300 BPL LOOK
00400 JMP FAO ;File already open error.
00500
00600 LOOK: JSR LOKUP ;Lookup file FNAM
00700 BEQ SETOPN
00800 CMPI 200 ;File not found code.
00900 BEQ NACKIT
01000 JMP DIRERR ;Directory read error
01100 NACKIT: JMP FNF ;File not found.
01200
01300 SETOPN: LDAZ FTRK ;Get track and sector
01400 STAZ CTRK
01500 LDAZ FSEC
01600 STAZ CSEC
01700 LDAZ NSEC ;Get file length.
01800 STAZ SREM
01900 ;Fill FBUF
02000 JSR RCMDR ;* NTRYS and no wait.
02100
02200 JSR SETSPO ;Point SPOINT to FBUF.
02300 LDAI 377
02400 STAZ RFOPEN
02500
02600 ACK: LDXI 6 ;<ack>
02700 OACK: JSR OCHR ;Output byte.
02800 JSR SPIN
02900 JMP IDLE ;No flag clear.
03000
03100 SETSPO: LDAI 0 ;Reset SI/O pointer.
03200 STAZ SPOINT
03300 LDAI FBUF⊗-10
03400 STAZ SPOH
03500 RTS
00100 ;Read a block of the file.
00200 READ: JSR GEOT ;Wait for EOT.
00300 BITZ RFOPEN ;Check if file open.
00400 BMI CKS
00500 JMP FNF ;File not found
00600 CKS: LDAZ SREM ;Check for end of file.
00700 BNE READO ;For FLEN = 0.
00800 EOF: LDXI 6 ;End of file error code.
00900 JMP OCLR ;Output X and clear flags.
01000
01100 READO: LDAI 0 ;Init check sum.
01200 STAZ CKSUM
01300 RW: BITZ BUSY ;Wait until not busy.
01400 BMI RW
01500 LDAZ ERFLG ;Check for *16 read error.
01600 BEQ NXTBUF
01700 ;Output 256 zeros?
01800 DRERR: LDXI 14 ;Disk read error.
01900 JMP OCLR
02000
02100 NXTBUF: DECZ SREM ;Check if end of file.
02200 DECZ SREM
02300 BEQ ACKIT
02400 ;Start read of next buffer.
02500 INCZ CSEC ;Next sector.
02600 INCZ CSEC
02700 LDAZ CSEC ;Check if next track.
02800 CMPI =16
02900 BCC RNS
03000 LDAI 1 ;First sector.
03100 STAZ CSEC
03200 INCZ CTRK ;Next track.
03300
03400 RNS: JSR SWDBUF ;Swap disk buffers.
03500 JSR MOTON ;Turn on motor.
03600 JSR RCMDR ;No wait.
03700 ACKIT: JSR PACK ;Output <ack>.
03800 JSR PSTX ;Output <stx>.
03900
04000 LDYI 0
04100 RDIT: LDAIY SPOINT ;Output a buffer full.
04200 TAX
04300 JSR OCHR
04400 TXA
04500 CLC
04600 ADCZ CKSUM
04700 STAZ CKSUM
04800 INY
04900 BNE RDIT
05000
05100 JSR SWSBUF ;Swap SI/O buffers.
05200 LDAZ CKSUM ;Output check sum.
05300 EORI 377
05400 TAX
05500 INX
05600 JMP OACK ;Output it and no flag clear.
05700
05800 SWSBUF: LDAZ SPOH
05900 EORI 1 ;Swap SI/O buffers.
06000 STAZ SPOH
06100 RTS
00100 ;Create file routine
00200 ENTR: BITZ WFOPEN ;Check if file already open
00300 BPL CLRFO
00400 FAO: LDXI 10 ;File already open error.
00500 JMP OACK ;Output it.
00600 CLRFO: LDAI 0 ;Put clear read file in RHDR?
00700 STAZ RFOPEN ;Close read file.
00800 LOKIT: JSR LOKUP ;Check if file already exists.
00900 BEQ FEXIST ;Check if file exists
01000 CMPI 200 ;Not in dir. code
01100 BEQ FULCK
01200 DIRERR: LDXI 13 ;Directory read error code.
01300 JMP OCLR ;Clear flags.
01400
01500 FEXIST: LDXI 2 ;File exists error code.
01600 JMP OCLR ;Clear flags.
01700
01800 DSKFUL: LDAI LASTRK ;Disk full. Check close?
01900 STAZ FFTRK ;Set full flag.
02000 LDXI 5 ;Disk full code.
02100 JMP OCLR ;Output and clear flags?
02200
02300 FULCK: LDAZ FFTRK ;Get first free track.
02400 CMPI LASTRK ;Check if disk full.
02500 BCS DSKFUL
02600
02700 STAZ CTRK ;Point to new file.
02800 STAZ FTRK ;Setup file block.
02900 STAZ CLEN ;Track number for seek.
03000 LDAI 151 ;Seek track command.
03100 STAZ CBLK
03200 LDAI 1
03300 STAZ CCNT
03400
03500 JSR RCMD ;Seek track.
03600
03700 LDAI 3 ;Setup command parameter count.
03800 STAZ CCNT
03900 STAZ DPOH ;Point disk to other buffer.
04000 LDAI 2 ;Setup number of sectors.
04100 STAZ CLEN
04200 LDXZ FFSEC
04300 STXZ FSEC ;Setup file block.
04400 DEX ;-1 For inc. before write.
04500 DEX
04600 STXZ CSEC
04700
04800 JSR SETSPO ;Point SI/O to FBUF.
04900 LDAI 0
05000 STAZ FLEN ;Reset file length.
05100
05200 LDAI 377 ;Set write file open flag.
05300 STAZ WFOPEN
05400 JMP ACK ;Return with no errors
00100 ;Write file.
00200 ;Fix full check for write last sector?
00300 WRITE: JSR GEOT ;Wait for EOT.
00400 BITZ WFOPEN ;Check if file open.
00500 BMI WIT
00600 JMP FNF ;File not found
00700 WIT: LDAZ FFTRK
00800 CMPI LASTRK ;Check if disk is full.
00900 BCS DSKFUL
01000
01100 LDAI 0
01200 STAZ CKSUM ;Init check sum.
01300
01400 JSR PACK ;Output <ACK>.
01500 JSR GCHR ;Wait for STX.
01600 CMPI 2 ;<STX>.
01700 BNE COMERR ;No STX.
01800 ;Check for COMERR?
01900
02000 LDYI 0
02100 WLOOP: JSR GCHR ;Fill FBUF.
02200 STAIY SPOINT
02300 CLC
02400 ADCZ CKSUM ;Update check sum.
02500 STAZ CKSUM
02600 INY
02700 BNE WLOOP
02800
02900 JSR GCHR ;Get check sum.
03000 CLC
03100 ADCZ CKSUM ;Check for check sum error.
03200 BNE COMERR
03300 LDAZ CEFLG ;Check for communication error.
03400 BEQ WBUF
03500 COMERR: LDXI 11 ;Communication error.
03600 JMP OCLR ;Reset flags.
03700
03800 WBUF: BITZ BUSY ;Wait until last buffer done.
03900 BMI WBUF
04000 LDAZ ERFLG ;Check for errors.
04100 BEQ NFBLK
04200 JMP DRERR ;Write error. Verify error?
04300 NFBLK: LDXZ CSEC ;Fix sector number.
04400 INX
04500 INX
04600 CPXI =16 ;Check if end of track.
04700 BCC SWBUF
04800 LDXI 1 ;First sector.
04900 INCZ CTRK ;Next track.
05000 LDAZ CTRK
05100 CMPI LASTRK ;Check if disk full?
05200 BCC SWBUF
05300 JMP DSKFUL
00100 SWBUF: STXZ CSEC ;Next sector.
00200 JSR SWDBUF ;Swap disk buffers.
00300 JSR MOTON ;Turn on motor.
00400 JSR WBUFR ;Write buffer.
00500
00600 JSR SWSBUF ;Swap SI/O buffers.
00700 INCZ FLEN ;Update file length.
00800 INCZ FLEN
00900 JMP ACK ;No error return.
01000
01100 WBUFR: LDAI 113 ;Write two sectors command.
01200 STAZ CBLK
01300 WUF: LDAI 377
01400 STAZ DIRC ;Set to write.
01500 JSR RCMDR ;* NTRYS.
01600 RTS
01700
01800 WBUFW: JSR WBUFR ;Write it.
01900 WW: BITZ BUSY
02000 BMI WW ;Wait until not busy.
02100 LDAZ ERFLG
02200 RTS
02300
02400 SWDBUF: LDAZ DPOH
02500 EORI 1 ;Swap disk buffers.
02600 STAZ DPOH
02700 RTS
00100 CLOZE: JSR GEOT ;Wait for EOT.
00200 BITZ WFOPEN ;Check if file open
00300 BMI UPDIR
00400 JMP FNF ;File not found.
00500
00600 ;Update directory
00700 UPDIR: BITZ BUSY ;Wait until not busy.
00800 BMI UPDIR
00900 LDAZ ERFLG ;Check for error.
01000 BEQ BUMP
01100 JMP DRERR ;Last buffer write error?
01200
01300 BUMP: LDAZ FLEN ;Save file length.
01400 STAZ NSEC
01500 LDAZ CTRK ;Save new FFTRK.
01600 STAZ HTRK
01700 LDXZ CSEC ;Point to next free data block.
01800 INX
01900 INX
02000 CPXI =16 ;Number of secs. per track +1.
02100 BCC FIXFF
02200 INCZ HTRK ;Next track.
02300 LDXI 1 ;First sector.
02400 FIXFF: STXZ HSEC ;Save new FFSEC.
02500
02600 ;Read directory header and last directory sector.
02700 JSR RHDR ;Read dir. header
02800 BNE RDE ;Dir. read error.
02900 LDXZ DSEC ;Last directory sector -1.
03000 INX ;Bump.
03100 STXZ CSEC
03200 STXZ SREM ;Save last dir. sec. number.
03300 JSR SWDBUF ;Swap bufs.for last dir. save.
03400 JSR RSEC ;Read next dir. sec.
03500 BEQ CLOZIT
03600 RDE: JMP DIRERR ;Directory read error.
03700
03800 CLOZIT: LDYZ FFDIR
03900
04000 LDXI 0 ;BLT FBLK into directory
04100 NAMEIT: LDAZX FBLK
04200 STAY FBUF1 ;Other buffer.
04300 INY
04400 INX
04500 CPXI 20 ;FBLK Length
04600 BCC NAMEIT
04700
04800 JSR WBUFW ;Write directory 0.
00100 ;Update directory header.
00200 WRTH0: CLC
00300 LDAZ FFDIR
00400 ADCI 20 ;Update end of dir.
00500 STAZ FFDIR
00600 BNE UPFF
00700 INCZ DSEC ;Next sector
00800 INCZ DSEC
00900 LDAZ DSEC ;Check if directory full.
01000 CMPI =15
01100 BCC UPFF
01200 LDAI =14 ;Last directory sector.
01300 STAZ DSEC
01400 LDAI LASTRK ;Set disk full.
01500 STAZ HTRK
01600 UPFF: LDAZ HSEC ;Point to next free block.
01700 STAZ FFSEC
01800 LDAZ HTRK
01900 STAZ FFTRK
02000 SEC
02100 LDAZ FBLKS
02200 SBCZ FLEN ;Update free blocks.
02300 STAZ FBLKS
02400 BCS SVSEC
02500 DECZ FBH
02600
02700 SVSEC: LDXI 7 ;Header length
02800 HLOOP: LDAZX DBLK ;BLT Header into directory
02900 STAX FBUF
03000 DEX
03100 BPL HLOOP
03200
03300 LDAI 1 ;First sector.
03400 STAZ CSEC
03500 JSR SWDBUF ;Swap disk buffers.
03600
03700 JSR WBUFW ;Write dir. header 0.
03800 LDAI LASTRK ;Last track
03900 STAZ CTRK
04000 JSR WBUFW ;Write dir. header 1.
04100 ;Write last track directory.
04200 LDAZ SREM ;Get last dir.sec. number.
04300 STAZ CSEC
04400 JSR SWDBUF ;Swap buffers.
04500 JSR WBUFW
04600 BNE CLZERR
04700
04800 LDAZ SVERR ;?
04900 BEQ CLOZD
05000 ;Close error.
05100 CLZERR: JMP DIRERR ;?
05200 CLOZD: STAZ WFOPEN ;Reset write file open flag.
05300 JMP ACK
00100 PSF: JSR GEOT
00200 JSR PACK ;<Ack>
00300 JSR GCHR ;Wait for SOH.
00400 CMPI 1 ;SOH
00500 BNE PSFERR
00600 JSR GCHR ;Wait for special function cmd.
00700 CMPI "Q" ;Compress holes.
00800 BNE CKF
00900 JSR GEOT ;Wait for EOT.
01000 JMP CMPRES
01100
01200 CKF: CMPI "F" ;Format disk.
01300 BNE CKI
01400 JMP FORM
01500 CKI: CMPI "I" ;Initialize directory.
01600 BEQ IDIR
01700 PSFERR: JMP ILLCMD ;Command error.
01800 ;Initialize directory.
01900 IDIR: JSR GEOT ;Wait for EOT.
02000 JSR MOTON ;Turn on motor.
02100 LDXI 10
02200 LDAI 0
02300 ZE: STAX FBUF ;Zero directory
02400 INX
02500 BNE ZE
02600 LDXI 7
02700 DIIL: LDAX DIT ;Init dir.
02800 STAX FBUF
02900 DEX
03000 BPL DIIL
03100
03200 LDXI 4
03300 SETC: LDAX ID0 ;Setup CBLK.
03400 STAZX CBLK
03500 DEX
03600 BPL SETC
03700
03800 JSR SETDPO
03900 JSR WBUFW ;Write first header and dir.
04000 LDAI LASTRK ;Last track.
04100 STAZ CTRK
04200 JSR WBUFW ;Init last directory.
04300
04400 BEQ OK ;Check for errors.
04500 LDAZ SVERR
04600 BNE IDERR
04700 OK: JMP ACK
04800 IDERR: LDXI 7 ;Init dir. error.
04900 JMP OCLR ;Reset flags.
05000
05100 DIT: DMARK
05200 2 ;# of sectors
05300 0 ;FFDB
05400 1 ;FFT
05500 1 ;FFS
05600 =264∧377 ;FBL?
05700 1 ;FBH
05800 0
00100 ;Delete file.
00200 KIL: JSR LOKUP
00300 BEQ KILIT
00400 FNF: LDXI 3 ;File not found.
00500 JMP OCLR
00600 KILIT: LDAI HMARK
00700 STAY 760 ;FBUF - 20
00800 JSR WBUFW ;Write and wait.
00900 BNE JDER
01000 LDAI LASTRK
01100 STAZ CTRK
01200 JSR WBUFW ;Write last dir. track.
01300 BEQ JACK ;No errors.
01400 JDER: JMP DIRERR ;Error.
01500
01600 DIR: JSR GEOT ;Wait for EOT.
01700 JSR RHDR ;Read header.
01800 BNE JDER
01900 LDAI 0 ;Point to start
02000 STAZ DIRCNT
02100 JACK: JMP ACK
02200
02300 NXTDIR: JSR GEOT ;Wait for EOT.
02400 LDXZ DIRCNT ;Check if at end.
02500 CPXZ DSEC ;Check if done.
02600 BCC NXD
02700 JMP EOF
02800
02900 NXD: INX
03000 INX
03100 STXZ DIRCNT ;Update directory count.
03200 INX ;Bump past dir. header.
03300 STXZ CSEC
03400 JSR PACK ;Output <ACK>.
03500
03600 JSR RSEC ;Read next directory sector.
03700 BNE JDER
03800
03900 JSR PSTX ;Output <STX>.
04000 LDYI 0
04100 DOL: LDAY FBUF ;Find file in FBUF.
04200 CMPI FMARK
04300 BNE NXBLK
04400
04500 LDAI =10 ;9 Chr file name + # of secs.
04600 STAZ HSEC
04700 LDXI ":"
04800 FBOUT: JSR OCHR ;Output it.
04900 INY
05000 LDXY FBUF ;Get FBLK.
05100 DECZ HSEC
05200 BPL FBOUT
05300
05400 NXBLK: TYA
05500 ORAI 17 ;Next file block.
05600 TAY
05700 INY
05800 BNE DOL
05900
06000 BEQ OEOT ;Jump.
00100 ;Output free blocks.
00200 BLKS: JSR GEOT ;Wait for EOT.
00300 JSR RHDR ;Read directory header.
00400 BNE DJ ;Directory read error.
00500 JSR PACK ;<ack>
00600 JSR PSTX ;Output STX.
00700 LDXZ FBLKS
00800 JSR OCHR
00900 LDXZ FBH
01000 JSR OCHR
01100 OEOT: LDXI 4 ;<EOT>.
01200 JMP OCLR ;Clear flags.
01300 ;Compress holes.
01400 CMPRES: JSR RHDR ;Read directory header.
01500 BNE DJ
01600 SQEZ: JSR RNDS
01700 BNE DJ
01800 LDYI 0
01900 CKHOL: LDAY FBUF
02000 CMPI FMARK ;Look for a hole.
02100 BNE HOLE
02200 TYA
02300 CLC
02400 ADCI 20 ;Next directory record.
02500 TAY
02600 BNE CKHOL
02700
02800 DECZ SREM ;SREM ← SREM + 2.
02900 DECZ SREM
03000 BNE SQEZ
03100 PACKED: JMP ACK ;Done.
03200 DJ: JMP DIRERR ;Directory read error.
03300
03400 ;Hole found.
03500 HOLE: LDAY 1013 ;FBUF + TRK#
03600 STAZ HTRK
03700 LDAY 1014 ;FBUF + SEC#
03800 STAZ HSEC
03900 STYZ SVHY ;Save hole dir. index.
04000 LDAZ CSEC
04100 STAZ SVHSEC ;Save hole dir. sector.
04200
04300 FINDF: TYA ;Find next file.
04400 CLC
04500 ADCI 20 ;Next dir. record.
04600 TAY
04700 BNE CKFIL
04800 DECZ SREM ;SREM ← SREM - 2.
04900 DECZ SREM
05000 BEQ PACKED ;Done.
05100 JSR RNDS ;Read next directory sector.
05200 BNE DJ ;Error.
05300 TAY ;Y ← 0.
05400 CKFIL: LDAY FBUF
05500 CMPI FMARK
05600 BNE FINDF
05700 ;File found. Save file address.
05800 JSR FMOV ;Save FBLK.
00100 ;Fill hole.
00200 FILLIT: LDAZ FTRK ;Point to file.
00300 STAZ CTRK
00400 LDAZ FSEC
00500 STAZ CSEC
00600 LDAI 123 ;Read two sectors command.
00700 STAZ CBLK
00800 JSR RCMDW ;Read it.
00900 BNE DJ
01000
01100 LDAZ HTRK ;Point to hole.
01200 STAZ CTRK
01300 LDAZ HSEC
01400 STAZ CSEC
01500 CLC
01600 ADCI 2 ;Next hole sectors.
01700 CMPI =17
01800 BCC WRIT
01900 INCZ HTRK ;Next track.
02000 LDAI 1 ;First sector.
02100 WRIT: STAZ HSEC
02200 JSR WBUFW ;Fill hole.
02300 BNE DJ ;?
02400
02500 DECZ NSEC ;NSEC ← NSEC - 2.
02600 DECZ NSEC
02700 BEQ CUPD ;Check if hole filled.
02800 LDAZ FSEC
02900 CLC
03000 ADCI 2 ;Next file sectors.
03100 CMPI =17
03200 BCC UPSEC
03300 INCZ FTRK ;Next track.
03400 LDAI 1 ;First sector.
03500 UPSEC: STAZ FSEC
03600 BNE FILLIT ;Jump.
03700
03800 CUPD: LDAZ SVHSEC ;Update directory.
03900 STAZ CSEC ;Get hole dir. sector.
04000 LDAI 0 ;Track zero.
04100 STAZ CTRK
04200 JSR RSEC ;Read hole dir. sector.
04300 BNE DJ ;?
04400
04500 LDXI 0
04600 LDYZ SVHY ;Get hole dir. index.
04700 UPBLK: LDAZX FBLK ;FBUF ← FBLK - TRK&SEC
04800 STAY FBUF
04900 INY
05000 INX
05100 CPXI 13 ;FNAME + FMARK & NSEC.
05200 BCC UPBLK
05300 JSR WBUFW ;Write new dir.
05400 BNE DJ ;?
05500 ;Find next file.
00100 GEOT: JSR GCHR ;Wait for EOT.
00200 CMPI 4 ;<EOT>
00300 BNE TERR
00400 LDAZ CEFLG ;Checkk for comm. error.
00500 BNE TERR
00600 RTS
00700 TERR: PLA ;Fix stack?
00800 PLA
00900 JMP ILLCMD ;?
01000
01100 FORM: JSR GEOT
01200 JSR MOTON ;Turn on motor.
01300 LDAI RESTOR
01400 JSR PCMD ;Seek track zero?
01500 RSTORW: BITZ BUSY ;Wait until at track zero.
01600 BMI RSTORW
01700
01800 JSR SETDPO ;Point to FBUF.
01900 LDXI 6
02000 CSLOP: LDAX FORMT ;Setup command list.
02100 STAZX CBLK
02200 DEX
02300 BPL CSLOP
02400
02500 TKOOP: LDXI 1 ;First sector.
02600 LDYI 0
02700 SCOOP: LDAZ FOTRK ;Get track number.
02800 STAY FBUF ;And setup I.D.s.
02900 INY
03000 LDAI 0
03100 STAY FBUF ;Head number.
03200 INY
03300 TXA
03400 STAY FBUF ;Sector number.
03500 INY
03600 LDAI 0
03700 STAY FBUF ;Length.
03800 INY
03900 INX ;Next sector.
04000 CPXI =17 ;Sectors per track +1.
04100 BCC SCOOP
04200
04300 JSR WUF ;Write buffer.
04400 FW: BITZ BUSY ;Wait until not busy.
04500 BMI FW
04600 ;Add verify 16 sectors?
04700 INCZ FOTRK ;Next track.
04800 LDAZ FOTRK
04900 CMPI =35
05000 BCC TKOOP
05100
05200 LDAZ SVERR ;Check for errors.
05300 BNE FERR
05400 JMP ACK
05500 FERR: JMP DIRERR
00100 ;Wait for input.
00200 GCHR: LDA SIOC ;Read SI/O status.
00300 LSRA ;Get rcvr. full bit.
00400 BCC GCHR
00500 ANDI 30 ;FE, OVR.
00600 BEQ GOT1
00700 STAZ CEFLG
00800 GOT1: LDA SIOD
00900 RTS
01000
01100 PACK: LDXI 6 ;Output <ack>.
01200 ;Output byte in X.
01300 OCHR: LDA SIOC ;Read SI/O status.
01400 ANDI 2 ;Transmiter full bit.
01500 BEQ OCHR
01600 STX SIOD ;Output it.
01700 RTS
01800 PSTX: LDXI 2 ;Output <stx>.
01900 BNE OCHR
02000
02100 MOTOFF: LDAI MOFF ;Turn motor off.
02200 JSR PCMD
02300 LDAI 0
02400 STAZ MO ;Motor on flag.
02500 RTS
02600
02700 ONES ← 6 ;6 = .98s, 7 = 1.15s.
02800 MOTON: BITZ MO ;Check if already on.
02900 BMI SPIN
03000 LDAI 377 ;Turn on motor.
03100 STAZ TL ;Setup motor time out.
03200 LDAI ONES
03300 STAZ TH
03400 LDAI MON ;Turn it on.
03500 JSR PCMD
03600
03700 LDXI 0 ;Wait for motor on delay.
03800 MW: DEX
03900 BNE MW
04000 DECZ TL
04100 BNE MW
04200 DECZ TH
04300 BNE MW
04400
04500 LDAI 377
04600 STAZ MO ;Set motor on flag.
04700 SPIN: LDAI 377 ;Setup motor time out.
04800 STAZ TL
04900 LDAI TWOS
05000 STAZ TH
05100 RTS
05200
05300 ;Reset and interrupt vectors.
05400 LOC ZERO + 177772
05500 NMIV∧377 ;NMI Vector.
05600 NMIV⊗-10
05700 RST∧377 ;Reset vector.
05800 RST⊗-10
05900 IRQV∧377 ;IRQ Vector.
06000 IRQV⊗-10
06100 END